package sns.app.nhwc;

import java.util.ArrayList;

public class NHWCGame {

	public static final int PLAYER_MAX = 4;
	public static final int PLAYER_MIN = 2;

	public static final int GAME_WAITING = 0;
	public static final int GAME_BEGIN = 1;

	private int gameId;
	private ArrayList<NHWCMessageInbound> connections;
	private String keyword;
	private int playerNum;
	private int preparedNum;
	private int gameState;
	private int drawerIndex;

	/**
	 * The constructor
	 */
	public NHWCGame(int gameId) {
		this.gameId = gameId;
		this.connections = new ArrayList<NHWCMessageInbound>(PLAYER_MAX);
		this.keyword = "";
		this.playerNum = 0;
		this.preparedNum = 0;
		this.gameState = GAME_WAITING;
		this.drawerIndex = -1;
	}

	/**
	 * Add a player to the arraylist
	 * 
	 * @param nhwcMessageInbound
	 * @return
	 */
	public boolean addPlayer(NHWCMessageInbound nhwcMessageInbound) {
		if (isFull()) {
			return false;
		} else {
			connections.add(nhwcMessageInbound);
			playerNum++;
			NHWCMessageInbound.sendMessageTo(NHWCMessageInbound
					.getProtocolFormat(NHWCMessageInbound.GAME_ROOM_NUM,
							gameId, -1), nhwcMessageInbound);
			return true;
		}
	}

	/**
	 * remove a player from the arraylist
	 * 
	 * @param nhwcMessageInbound
	 * @return
	 */
	public boolean removePlayer(NHWCMessageInbound nhwcMessageInbound) {
		if (connections.contains(nhwcMessageInbound)) {
			if (nhwcMessageInbound.getState() == NHWCMessageInbound.PREPARING) {
				preparedNum--;
			}
			connections.remove(nhwcMessageInbound);
			playerNum--;
			if (playerNum < PLAYER_MIN) {
				initGame();
			} else {
				checkWhetherToStart();
			}
			return true;
		} else {
			return false;
		}

	}

	/**
	 * check if the players list are full
	 * 
	 * @return
	 */
	public boolean isFull() {
		return playerNum >= PLAYER_MAX;
	}

	/**
	 * check if the game is waiting to start
	 * 
	 * @return
	 */
	public boolean isWaiting() {
		return gameState == GAME_WAITING;
	}

	/**
	 * get the connections of all the players
	 * 
	 * @return
	 */
	public ArrayList<NHWCMessageInbound> getConnections() {
		return connections;
	}

	/**
	 * get the keyword of the game
	 * 
	 * @return
	 */
	public String getKeyword() {
		return keyword;
	}

	/**
	 * get the playerNum
	 * 
	 * @return
	 */
	public int getPlayerNum() {
		return playerNum;
	}

	/**
	 * get the preparedNum
	 * 
	 * @return
	 */
	public int getPreparedNum() {
		return preparedNum;
	}

	/**
	 * increase preparedNum by 1
	 */
	public void increasePreparedNum() {
		preparedNum++;
	}

	/**
	 * check whether we can start the game start the game if we can
	 */
	public void checkWhetherToStart() {
		// the number of players should be greater than 1
		if (playerNum < PLAYER_MIN) {
			return;
		}
		if (preparedNum < playerNum) {
			return;
		}
		startGame();
	}

	/**
	 * start the game the method can only be called in the checkWhetherToStart()
	 */
	private void startGame() {
		// generate the keyword for the game
		generateKeyword();
		// get the random drawer
		drawerIndex = Util.getRandom(0, playerNum);
		NHWCMessageInbound connection = connections.get(drawerIndex);
		// send message to the drawer
		connection.setState(NHWCMessageInbound.DRAWER_DRAWING);
		NHWCMessageInbound.sendMessageTo("游戏开始，你是画家，关键词：" + getKeyword(),
				connection);
		NHWCMessageInbound.sendMessageTo(NHWCMessageInbound
				.getProtocolFormat(NHWCMessageInbound.GAME_DRAWER), connection);
		// send message to all the other guessers
		for (int i = 0; i < playerNum; i++) {
			if (i != drawerIndex) {
				connection = connections.get(i);
				connection.setState(NHWCMessageInbound.GUESSER_GUESSING);
				NHWCMessageInbound.sendMessageTo(NHWCMessageInbound
						.getProtocolFormat(NHWCMessageInbound.GAME_GUESSER),
						connection);
			}
		}
		gameState = GAME_BEGIN;
	}

	/**
	 * check whether to finish the game, i.e. is anyone get the answer if so,
	 * call winGame() to send necessary messages to the players
	 * 
	 * @param message
	 * @param connection
	 */
	public void checkWhetherToFinish(String message,
			NHWCMessageInbound connection) {
		// skip the drawer's message
		if (connection == connections.get(drawerIndex)) {
			return;
		}
		if (message.trim().equals(getKeyword())) {
			winGame(connection);
		}
	}

	/**
	 * some player get the answer and send winning messages to all the others
	 * 
	 * @param nhwcMessageInbound
	 */
	public void winGame(NHWCMessageInbound nhwcMessageInbound) {
		for (NHWCMessageInbound connection : connections) {
			if (connection == nhwcMessageInbound) {
				NHWCMessageInbound.sendMessageTo("* 你猜对啦，好厉害！", connection);
			} else if (connection.getState() == NHWCMessageInbound.DRAWER_DRAWING) {
				NHWCMessageInbound.sendMessageTo("* 有人猜对啦，你 画的真好！", connection);
			} else {
				NHWCMessageInbound.sendMessageTo("* 你没有猜对，再接再厉！", connection);
			}
			// send new game instruction
			connection.setState(NHWCMessageInbound.NOT_PREPARING);
			NHWCMessageInbound.broadcast(NHWCMessageInbound
					.getProtocolFormat(NHWCMessageInbound.GAME_INIT),
					connections);
		}
		initGame();
	}

	/**
	 * end the game
	 */
	public void initGame() {
		gameState = GAME_WAITING;
		keyword = "";
		drawerIndex = -1;
		preparedNum = 0;
	}

	/**
	 * generate the keyword for the game
	 */
	private void generateKeyword() {
		KeywordDictionary kd = KeywordDictionary.getInstance();
		int index = Util.getRandom(0, kd.getKeywordNum());
		keyword = kd.getKeywordAtIndex(index);
	}
	
	/**
	 * check if the game is available
	 * 
	 * @return
	 */
	public boolean isAvailable(){
		return !isFull() && isWaiting();
	}
	
	public int getGameId(){
		return gameId;
	}
	
	public int getGameState(){
		return gameState;
	}
	
}
